package fr.castorflex.openharmony.circularprogressbar;

import fr.castorflex.openharmony.circularprogressbar.util.ResUtil;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.Text;
import ohos.agp.render.Canvas;
import ohos.agp.utils.Rect;
import ohos.app.Context;

public class CircularProgressBar extends Text implements Component.LayoutRefreshedListener, Component.DrawTask {
    private CircularProgressDrawable.Builder builder;
    private AttrSet mAttrSet;
    private Context mContext;
    private int color;
    private float mStrokeWidth = 10.0f;
    private float sweepSpeed;
    private float rotationSpeed;
    private int colorsId;
    private int minSweepAngle;
    private int maxSweepAngle;
    private static final String cpb_default_color = "cpb_default_color";
    private static final String cpb_default_stroke_width = "cpb_default_stroke_width";
    private static final String cpb_default_sweep_speed = "cpb_default_sweep_speed";
    private static final String cpb_default_rotation_speed = "cpb_default_rotation_speed";
    private static final String cpb_colors = "cpb_colors";
    private static final String cpb_default_min_sweep_angle = "cpb_default_min_sweep_angle";
    private static final String cpb_default_max_sweep_angle = "cpb_default_max_sweep_angle";
    private CircularProgressDrawable mAnimatedDrawable;
    private int[] colorsArray;

    public CircularProgressBar(Context context, AttrSet attrs) {
        super(context, attrs);
        mContext = context;

        if (attrs != null) {
            mAttrSet = attrs;
            color = mAttrSet.getAttr(cpb_default_color).isPresent() ?
                    mAttrSet.getAttr(cpb_default_color).get().getColorValue().getValue() : 0x33b5e5;
            mStrokeWidth = mAttrSet.getAttr(cpb_default_stroke_width).isPresent() ?
                    mAttrSet.getAttr(cpb_default_stroke_width).get().getFloatValue() : 10.0f;
            sweepSpeed = mAttrSet.getAttr(cpb_default_rotation_speed).isPresent() ?
                    mAttrSet.getAttr(cpb_default_rotation_speed).get().getIntegerValue() : 1;
            rotationSpeed = mAttrSet.getAttr(cpb_default_rotation_speed).isPresent() ?
                    mAttrSet.getAttr(cpb_default_rotation_speed).get().getIntegerValue() : 1;
            colorsId = mAttrSet.getAttr(cpb_colors).isPresent() ?
                    mAttrSet.getAttr(cpb_colors).get().getIntegerValue() : 1;
            minSweepAngle = mAttrSet.getAttr(cpb_default_min_sweep_angle).isPresent() ?
                    mAttrSet.getAttr(cpb_default_min_sweep_angle).get().getIntegerValue() : 20;
            maxSweepAngle = mAttrSet.getAttr(cpb_default_max_sweep_angle).isPresent() ?
                    mAttrSet.getAttr(cpb_default_max_sweep_angle).get().getIntegerValue() : 300;
        } else {
            color = 0x33b5e5;
            mStrokeWidth = 10.0f;
            sweepSpeed = 1;
            rotationSpeed = 1;
            colorsId = 2;
            minSweepAngle = 20;
            maxSweepAngle = 300;
        }

        if (colorsId != 0) {
            colorsArray = new int[]{ResUtil.getColor(context, ResourceTable.Color_cpb_default_color)};
        }

        builder = new CircularProgressDrawable.Builder(mContext)
                .sweepSpeed(sweepSpeed)
                .rotationSpeed(rotationSpeed)
                .strokeWidth(mStrokeWidth)
                .minSweepAngle(minSweepAngle)
                .maxSweepAngle(maxSweepAngle);

        if (colorsArray != null && colorsArray.length > 0)
            builder.colors(colorsArray);

        setLayoutRefreshedListener(this::onRefreshed);
        addDrawTask(this::onDraw);
    }

    boolean mIndeterminateProgressMode = true;

    @Override
    public void onRefreshed(Component component) {
        if (mIndeterminateProgressMode) {
            invalidate();
        }
    }

    public void setColors(int[] colorsInput) {
        colorsArray = colorsInput;
        builder.colors(colorsArray);
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        drawIndeterminateProgress(canvas);
    }

    private void drawIndeterminateProgress(Canvas canvas) {
        if (mAnimatedDrawable == null) {
            mAnimatedDrawable = builder.build();
            int left = 5;
            int right = getWidth() / 2;
            int bottom = getWidth() / 2;
            int top = 5;
            mAnimatedDrawable.onBoundsChange(new Rect(left, top, right, bottom));
            mAnimatedDrawable.setComponent(this);
            mAnimatedDrawable.start();
            mAnimatedDrawable.drawToCanvas(canvas);

        } else {
            mAnimatedDrawable.drawToCanvas(canvas);
        }
    }

    private CircularProgressDrawable checkIndeterminateDrawable() {
        return mAnimatedDrawable;
    }

    public void progressiveStart() {
        if (checkIndeterminateDrawable() != null) {
            checkIndeterminateDrawable().start();
        }
    }

    public void progressiveStop() {
        if (checkIndeterminateDrawable() != null) {
            checkIndeterminateDrawable().stop();
        }
    }

    public void setCircularProgressDrawableStrokeWidth(float strokeWidth) {
        mStrokeWidth = strokeWidth;
        if (checkIndeterminateDrawable() != null) {
            checkIndeterminateDrawable().setStrokeWidth(mStrokeWidth);
        } else {
            builder.strokeWidth(mStrokeWidth);
        }
    }

    public void setCircularProgressDrawableSpeed(float speed) {
        sweepSpeed = speed;
        rotationSpeed = speed;
        update();
    }

    private void update() {
        builder = new CircularProgressDrawable.Builder(mContext)
                .sweepSpeed(sweepSpeed)
                .rotationSpeed(rotationSpeed)
                .strokeWidth(mStrokeWidth)
                .minSweepAngle(minSweepAngle)
                .maxSweepAngle(maxSweepAngle);

        if (colorsArray != null && colorsArray.length > 0)
            builder.colors(colorsArray);
        mAnimatedDrawable = null;
    }
}
